$.dd.Drag = $.extend($.util.Observable, {
	isDrag: false
	,startX: null
	,startY: null
	
	,x: null
	,y: null
	
	,data: null
	
	,cursorDrag: 'move'
	
	,constructor: function(el, config){
		$.apply(this, config);
		this.el = $.get(el);
		
		this.addEvents(
			'beforestart'
			,'start'
			,'drag'
			,'drop'
		);
		
		$.dd.Drag.superclass.constructor.call(this, config);
		
		this.init();
	}
	
	,init: function(){
		var me = this
			,dragEl = me.getDragEl();
		
		dragEl.setStyle({position: 'absolute'});
		dragEl.dom.draggable = true;
		
		var offsetX, offsetY;
		var start = false
			,oldCursor = dragEl.getStyle('cursor');
		
		me.el.on('mousedown', function(e){
			if(false === me.fireEvent('beforestart', me, e)) return me;
			
			me.isDrag = true;			
			dragEl.setStyle({cursor: me.dragCursor});
			
			me.startX = me.el.getX();
			me.startY = me.el.getY();
			
			offsetX = e.xy[0] - me.startX;
			offsetY = e.xy[1] - me.startY;
		});
		
		var docEl = $.get(document);
		docEl.on('mousemove', function(e){
			if(me.isDrag){
				if(!start){
					start = true;
					dragEl.show();
					$.dd.Manager.drag = me;
					
					me.fireEvent('start', me, e, [me.startX, me.startY]);
				}
				var x = null !== me.x? e.xy[0] + me.x : e.xy[0] - offsetX
					,y = null !== me.y? e.xy[1] + me.y : e.xy[1] - offsetY;
				
				dragEl.setXY([x, y]);
				
				me.fireEvent('drag', me, e, [x, y]);
			}
		});
		
		docEl.on('mouseup', function(e){
			me.isDrag = false;
			start = false;
			me.getDropEl().setStyle({cursor: oldCursor});
			
			if(false === me.fireEvent('drop', me, e, me.data)){
				dragEl.shift({
					x: me.startX
					,y: me.startY
					,callback: function(){
						//if(dragEl !== me.el) dragEl.remove();
					}	
				});
			}else{
				//if(dragEl !== me.el) dragEl.remove();
			}
			
			$.dd.Manager.drag = null;
		});
	}
	
	,getEl: function(){
		return this.el;	
	}
	
	,getDragEl: function(){
		return this.getEl();	
	}
	
	,getDropEl: function(){
		return this.getEl();	
	}
	
	,getData: function(){
		return this.data;	
	}
	
	,setData: function(data){
		this.data = data;
		return this;	
	}
});